package cn.iocoder.yudao.module.iot.dal.redis.device;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 设备能源数据 Redis DAO
 *
 * @author 芋道源码
 */
@Repository
@Slf4j
public class DeviceEnergyRedisDAO {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final String ENERGY_DATA_KEY = "iot:device:energy:data:%d";
    private static final String ENERGY_HISTORY_KEY = "iot:device:energy:history:%d";
    private static final String ENERGY_LATEST_KEY = "iot:device:energy:latest:%d";
    
    private static final int MAX_HISTORY_SIZE = 50; // 最大历史记录数量
    private static final int EXPIRE_DAYS = 7; // 数据过期时间（天）

    /**
     * 保存能源数据
     */
    public void saveEnergyData(Long deviceId, Map<String, Object> energyData) {
        if (energyData == null || energyData.isEmpty()) {
            return;
        }

        String dataKey = String.format(ENERGY_DATA_KEY, deviceId);
        String historyKey = String.format(ENERGY_HISTORY_KEY, deviceId);
        String latestKey = String.format(ENERGY_LATEST_KEY, deviceId);

        try {
            // 1. 保存最新数据
            String latestDataJson = JsonUtils.toJsonString(energyData);
            stringRedisTemplate.opsForValue().set(latestKey, latestDataJson, EXPIRE_DAYS, TimeUnit.DAYS);

            // 2. 添加到历史记录
            String historyDataJson = JsonUtils.toJsonString(energyData);
            stringRedisTemplate.opsForList().leftPush(historyKey, historyDataJson);
            
            // 3. 限制历史记录数量
            stringRedisTemplate.opsForList().trim(historyKey, 0, MAX_HISTORY_SIZE - 1);
            
            // 4. 设置过期时间
            stringRedisTemplate.expire(historyKey, EXPIRE_DAYS, TimeUnit.DAYS);

            log.debug("[saveEnergyData][设备({}) 能源数据保存成功]", deviceId);
        } catch (Exception e) {
            log.error("[saveEnergyData][设备({}) 能源数据保存失败]", deviceId, e);
        }
    }

    /**
     * 获取能源数据历史记录
     */
    public List<Map<String, Object>> getEnergyHistory(Long deviceId, int limit) {
        String historyKey = String.format(ENERGY_HISTORY_KEY, deviceId);
        
        try {
            List<String> historyList = stringRedisTemplate.opsForList().range(historyKey, 0, limit - 1);
            if (CollUtil.isEmpty(historyList)) {
                return new ArrayList<>();
            }

            List<Map<String, Object>> result = new ArrayList<>();
            for (String dataJson : historyList) {
                if (StrUtil.isNotEmpty(dataJson)) {
                    try {
                        Map<String, Object> data = JsonUtils.parseObject(dataJson, Map.class);
                        if (data != null) {
                            result.add(data);
                        }
                    } catch (Exception e) {
                        log.warn("[getEnergyHistory][设备({}) 解析历史数据失败: {}]", deviceId, dataJson, e);
                    }
                }
            }
            
            return result;
        } catch (Exception e) {
            log.error("[getEnergyHistory][设备({}) 获取能源历史数据失败]", deviceId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取最新能源数据
     */
    public Map<String, Object> getLatestEnergy(Long deviceId) {
        String latestKey = String.format(ENERGY_LATEST_KEY, deviceId);
        
        try {
            String latestDataJson = stringRedisTemplate.opsForValue().get(latestKey);
            if (StrUtil.isEmpty(latestDataJson)) {
                return null;
            }
            
            return JsonUtils.parseObject(latestDataJson, Map.class);
        } catch (Exception e) {
            log.error("[getLatestEnergy][设备({}) 获取最新能源数据失败]", deviceId, e);
            return null;
        }
    }

    /**
     * 删除设备能源数据
     */
    public void deleteEnergyData(Long deviceId) {
        String dataKey = String.format(ENERGY_DATA_KEY, deviceId);
        String historyKey = String.format(ENERGY_HISTORY_KEY, deviceId);
        String latestKey = String.format(ENERGY_LATEST_KEY, deviceId);
        
        try {
            stringRedisTemplate.delete(Arrays.asList(dataKey, historyKey, latestKey));
            log.debug("[deleteEnergyData][设备({}) 能源数据删除成功]", deviceId);
        } catch (Exception e) {
            log.error("[deleteEnergyData][设备({}) 能源数据删除失败]", deviceId, e);
        }
    }
} 